/***************************************************************************
 *   Copyright (C) 2007 by Grzegorz Latarowski   *
 *   g.latarowski@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

// local
#include "marker.h"



// ===========================================================================
//                                   GMarker
// ===========================================================================


// --------------------------- GMarker::GMarker() ----------------------------
GMarker::GMarker( QGraphicsItem * pItem )
	: GGraph( pItem )
{
	setFlags( ItemIsMovable );
	QGraphicsItem::setCursor( QCursor( Qt::SizeAllCursor ) );
	
		//set deaefult color as white
	_color = Qt::white;
	
		// create hooks on top of marker
	_pHook1 = new GNode( this );
	_pHook2 = new GNode( this );
	_pHook1->setZValue( zValue() + 0.01 );
	_pHook2->setZValue( zValue() + 0.01 );
	
	_pHook1->setToolTip( tr( "Move hook around the scene to rotate the marker." ) );
	_pHook2->setToolTip( tr( "Move hook around the scene to rotate the marker." ) );
}
// ---------------------------------------------------------------------------


// --------------------------- GMarker::GMarker() ----------------------------
GMarker::GMarker( const QPointF hook1Pos, const QPointF hook2Pos,
				  QGraphicsItem * pItem )
	: GGraph( pItem )
{
	setFlags( QGraphicsItem::ItemIsMovable );
	QGraphicsItem::setCursor( QCursor( Qt::SizeAllCursor ) );
	
		//set deaefult color as white
	_color = Qt::white;
	
		// create hooks on top of marker
	_pHook1 = new GNode( this );
	_pHook2 = new GNode( this );
	_pHook1->setZValue( zValue() + 0.01 );
	_pHook2->setZValue( zValue() + 0.01 );
	
	_pHook1->setToolTip( tr( "Move hook around the scene to rotate the marker." ) );
	_pHook2->setToolTip( tr( "Move hook around the scene to rotate the marker." ) );
	
	setHooks( hook1Pos, hook2Pos );
}
// ---------------------------------------------------------------------------


// --------------------------- GMarker::GMarker() ----------------------------
GMarker::GMarker( const QColor color, QGraphicsItem * pItem )
	: GGraph( pItem ), _color( color )
{
	setFlags( QGraphicsItem::ItemIsMovable );
	QGraphicsItem::setCursor( QCursor( Qt::SizeAllCursor ) );
	
		// create hooks on top of marker
	_pHook1 = new GNode( this );
	_pHook2 = new GNode( this );
	_pHook1->setZValue( zValue() + 0.01 );
	_pHook2->setZValue( zValue() + 0.01 );
	
	_pHook1->setToolTip( tr( "Move hook around the scene to rotate the marker." ) );
	_pHook2->setToolTip( tr( "Move hook around the scene to rotate the marker." ) );
}
// ---------------------------------------------------------------------------


// --------------------------- GMarker::GMarker() ----------------------------
GMarker::GMarker( const QPointF hook1Pos, const QPointF hook2Pos,
				  const QColor color, QGraphicsItem * pItem )
	: GGraph( pItem ), _color( color )
{
	setFlags( QGraphicsItem::ItemIsMovable );
	QGraphicsItem::setCursor( QCursor( Qt::SizeAllCursor ) );

		// create hooks on top of marker
	_pHook1 = new GNode( this );
	_pHook2 = new GNode( this );
	_pHook1->setZValue( zValue() + 0.01 );
	_pHook2->setZValue( zValue() + 0.01 );
	
	_pHook1->setToolTip( tr( "Move hook around the scene to rotate the marker." ) );
	_pHook2->setToolTip( tr( "Move hook around the scene to rotate the marker." ) );
	
	setHooks( hook1Pos, hook2Pos );
}
// ---------------------------------------------------------------------------


// --------------------------- GMarker::~GMarker() ---------------------------
GMarker::~GMarker()
{
	if ( _pHook1 ) delete _pHook1;
	if ( _pHook2 ) delete _pHook2;
}
// ---------------------------------------------------------------------------


// --------------------------- GMarker::setZValue() --------------------------
void GMarker::setZValue( const qreal z )
{
		// change items z value
	QGraphicsItem::setZValue( z );
		// change hooks z value, hook on top of marker
	if ( _pHook1 ) _pHook1->setZValue( zValue() + 0.01 );
	if ( _pHook2 ) _pHook2->setZValue( zValue() + 0.01 );
}
// ---------------------------------------------------------------------------


// --------------------- GMarker::setHooks() ---------------------------------
void GMarker::setHooks( const QPointF & pos1, const QPointF & pos2 )
{
	if( scene() ) _boundingRect = scene()->sceneRect();
	
	if( _pHook1 ) _pHook1->setPos( pos1 );
	if( _pHook2 ) _pHook2->setPos( pos2 );
	
	adjust();
}
// ---------------------------------------------------------------------------


// --------------------- GMarker::hooks() ------------------------------------
QPolygonF GMarker::hooks()const
{
	QPolygonF hooks;
	
	if( _pHook1 ) hooks << _pHook1->pos();
	if( _pHook2 ) hooks << _pHook2->pos();
	
	return hooks;
}
// ---------------------------------------------------------------------------


// ----------------------- GMarker::boundingRect() ---------------------------
QRectF GMarker::boundingRect() const
{
	return _boundingRect;
}
// ---------------------------------------------------------------------------


// -------------------------- GMarker::shape() -------------------------------
QPainterPath GMarker::shape() const
{
	double extra = 4;
	
	// create strip of the size 2*extra
	
	QLineF forward( _markerLine.p1(), _markerLine.p2() );
	QLineF fNormal = forward.normalVector();
	fNormal.setLength( extra );
	QPointF p1 = fNormal.p2();
	fNormal.setLength( -2*extra );
	QPointF p2 = fNormal.p2();
	
	QLineF backward( _markerLine.p2(), _markerLine.p1() );
	QLineF bNormal = backward.normalVector();
	bNormal.setLength( extra );
	QPointF p3 = bNormal.p2();
	bNormal.setLength( -2*extra );
	QPointF p4 = bNormal.p2();
	
	QPainterPath shape( p1 );
	shape.lineTo( p2 );
	shape.lineTo( p3 );
	shape.lineTo( p4 );
	shape.closeSubpath();
	return shape;
}
// ---------------------------------------------------------------------------


// ------------------------- GMarker::paint() --------------------------------
void GMarker::paint( QPainter * pPainter,
					 const QStyleOptionGraphicsItem * option,
					 QWidget * widget )
{
	Q_UNUSED( widget );
	if ( !pPainter ) return;
	
	QPen pen( _color, 2 );
	if (option->state & QStyle::State_Sunken )
        pen.setColor( _color.light() );
	
	pPainter->setPen( pen );
	pPainter->drawLine( _markerLine );
	
		// draw colored path
	pPainter->setPen( QPen( Qt::NoPen ) );
	QColor color( _color );
	color.setAlpha( 80 );
	pPainter->setBrush( color );
	pPainter->drawPath( _coloredPath );
}
// ---------------------------------------------------------------------------


// ---------------------- GMarker::adjust() ----------------------------------
void GMarker::adjust()
{
		// if hooks not exists return empty line
	if( !_pHook1 || !_pHook2 )
	{
		_markerLine = QLineF();
		_coloredPath = QPainterPath();
		return;
	}
	
	if( scene() ) _boundingRect = scene()->sceneRect();
	
	// calculate line through hooks starting
	// and ending on the edge of _boundingRect
	
	// create lines which will help searching intersecting points

		// start line expands through startPoint
	QLineF startLine( mapFromScene( _pHook2->pos() ), mapFromScene( _pHook1->pos() ) );
	startLine.setLength( qMax( _boundingRect.width(), _boundingRect.height() ) + 1000 );
		// end line expands through endPoint
	QLineF endLine( mapFromScene( _pHook1->pos() ), mapFromScene( _pHook2->pos() ) );
	endLine.setLength( qMax( _boundingRect.width(), _boundingRect.height() ) + 1000 );
	
		// _boundingRect edges
	QLineF left( mapFromScene( _boundingRect.bottomLeft() ),
				 mapFromScene( _boundingRect.topLeft() ) );
	QLineF top( mapFromScene( _boundingRect.topLeft() ),
				mapFromScene( _boundingRect.topRight() ) );
	QLineF right( mapFromScene( _boundingRect.topRight() ),
				  mapFromScene( _boundingRect.bottomRight() ) );
	QLineF bottom( mapFromScene( _boundingRect.bottomRight() ),
				   mapFromScene( _boundingRect.bottomLeft() ) );
	
		// create vector from boundingRect edges
	QVector< QLineF > edges;
	edges << left << top << right << bottom;
	
		// search for startPoint and endPoint through edges
		// store edges numbers
	QPointF startPoint, endPoint;
	int startEdgeNum = -1;
	int endEdgeNum = -1;
	for( int i = 0; i < edges.size(); i++ )
	{
		QPointF intersectingPoint;
			// if edge intersects with startPoint expaned line than
			// this is markers starting point
		if( startLine.intersect( edges[i], & intersectingPoint )
				  == QLineF::BoundedIntersection )
		{
			startPoint = intersectingPoint;
			startEdgeNum = i;
		}
			// this must be markers endPoint
		if( endLine.intersect( edges[i], & intersectingPoint )
				  == QLineF::BoundedIntersection )
		{
			endPoint = intersectingPoint;
			endEdgeNum = i;
		}
	}
	
		// create colored path
	QPainterPath coloredPath;
	if( startEdgeNum <= endEdgeNum )
	{
		coloredPath.moveTo( startPoint );
		for( int i = startEdgeNum; i < endEdgeNum; i ++ )
			coloredPath.lineTo( edges[i].p2() );
		
		coloredPath.lineTo( endPoint );
		coloredPath.closeSubpath();
	}
	else
	{
		coloredPath.moveTo( startPoint );
		for( int i = startEdgeNum; i < edges.size(); i++ )
			coloredPath.lineTo( edges[i].p2() );
		
        for( int i = 0; i < endEdgeNum; i++ )
			coloredPath.lineTo( edges[i].p2() );
		
		coloredPath.lineTo( endPoint );
		coloredPath.closeSubpath();
	}
	
		// update all stuff
	removeFromIndex();
	_markerLine = QLineF( startPoint, endPoint );
	_coloredPath = coloredPath;
	addToIndex();
	
	update();
}
// ---------------------------------------------------------------------------


// -------------------------- GMarker::mouseMoveEvent() ----------------------
void GMarker::mouseMoveEvent( QGraphicsSceneMouseEvent * event )
{
	QPointF move = event->scenePos() - event->lastScenePos();
	
	if( _pHook1 ) _pHook1->moveBy( move.x(), move.y() );
	if( _pHook2 ) _pHook2->moveBy( move.x(), move.y() );
	
		// update marker
	adjust();
}
// ---------------------------------------------------------------------------


// eof
